﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace tank
{
    class _Enemy
    {
        public Point Location { get; set; }
        public Size Size { get; set; }
        public _Orientation Or { get; set; }
        public int Velocity { get; set; }
        public const int MapWidht = 15;
        public const int MapHeight = 20;
        public const int Side = 48;
        float[,] field { get; set; }
        public bool IsRunning { get; set; }
        public bool IsMoving { get; set; }
        int[,] cMap = new int[MapHeight, MapWidht];
        public int secondX { get; set; }
        public int secondY { get; set; }
        int posX, posY;
        public Rectangle Rectangle
        {
            get { return new Rectangle(Location, Size); }
        }
        public int LevelEnemy { get; set; }

        public _Bullet Bullet { get; set; }

        int maxWidth, maxHeight;

        Random rnd = new Random(DateTime.Now.Millisecond);

        public _Enemy(Point startPosition, int maxWidth, int maxHeight, float[,] field)
        {
            Location = startPosition;
            Size = new Size(42, 42);
            Or = _Orientation.Down;
            Velocity = 1;
            this.field = field;
            Bullet = new _Bullet(maxWidth, maxHeight, Or);

            this.maxWidth = maxWidth;
            this.maxHeight = maxHeight;

            LevelEnemy = 1;
            posX = Location.X / Side;
            posY = Location.Y / Side;

            timerForShoot = maxWidth / (4 * Velocity);
            FindWave((int)(Location.X / Side), (int)(Location.Y / Side), 9, 12);
        }
        int timeForNewOr;
        int timerForShoot;
        public void Update(ref List<_Block> blocks, ref List<_Hero> heroes, List<_Enemy> enemys, bool IsMoving)
        {
            this.secondX = secondX;
            this.secondY = secondY;
            this.IsMoving = IsMoving;
            if (!IsMoving)
            {
                if ((double)Location.X / (double)Side >= Location.X / Side + 0.1 && Or == _Orientation.Left)
                    posX = Location.X / Side+1;
                else posX = Location.X / Side;
                if ((double)Location.Y / (double)Side >= Location.Y / Side + 0.1 && Or == _Orientation.Up)
                    posY = Location.Y / Side+1;
                else posY = Location.Y / Side;

                if (cMap[posX, posY] > cMap[posX, posY + 1] && cMap[posX, posY + 1] >= 0)
                {
                    secondY = posY + 1; secondX = posX; Or = _Orientation.Down;
                }
                else if (cMap[posX, posY] > cMap[posX + 1, posY] && cMap[posX + 1, posY] >= 0)
                {
                    secondY = posX; secondX = posX + 1; Or = _Orientation.Right;
                }
                else if (cMap[posX, posY] > cMap[posX - 1, posY] && cMap[posX - 1, posY] >= 0)
                {
                    secondY = posY; secondX = posX - 1; Or = _Orientation.Left;
                }
                else if (cMap[posX, posY] > cMap[posX, posY - 1] && cMap[posX, posY - 1] >= 0)
                {
                    secondY = posY - 1; secondX = posX; Or = _Orientation.Up;
                }

            }

            int dx = 0, dy = 0;

            if (Or == _Orientation.Up)
                dy = -Velocity;
            else
                if (Or == _Orientation.Down)
                    dy = Velocity;
                else
                    if (Or == _Orientation.Left)
                        dx = -Velocity;
                    else
                        if (Or == _Orientation.Right)
                            dx = Velocity;


            Rectangle rect = new Rectangle(Location, Size);
            rect.Offset(dx, dy);

            bool intersect = false;

            foreach (_Hero hero in heroes)
            {
                if (RectIntersect(new Rectangle(hero.Location, hero.Size), rect))
                    intersect = true;
            }

            foreach (_Block block in blocks)
            {
                if (block.BlockType != _BlockType.Place_Green)
                if (RectIntersect(new Rectangle(block.Location, block.Size), rect))
                    intersect = true;
            }
            foreach (_Enemy enemy in enemys)
            {
                if (enemy != this)
                    if (RectIntersect(new Rectangle(enemy.Location, enemy.Size), rect))
                        intersect = true;
            }

            if (rect.Top > 0 && rect.Bottom < maxHeight && rect.Left > 0 && rect.Right < maxWidth&&!intersect)
                Location = rect.Location;

            timeForNewOr++;
            //if (timeForNewOr == 28)
            //{
            //    timeForNewOr = 0;
            //    NewOrientation();
            //}
            timerForShoot++;
            if (timerForShoot > maxWidth /(4* Velocity))
            {
                if (!Bullet.IsRunning)
                    StartShoot();
                timerForShoot = 0;
            }
            Bullet.Update(ref blocks);
            for (int i = 0; i < heroes.Count; i++)
            {
                if (RectIntersect(Bullet.Rectangle, heroes[i].Rectangle))
                {
                    heroes.RemoveAt(i);
                    i--;
                    Bullet.Reset();
                }
            }
        }

        public void FindWave(int startY, int startX, int targetY, int targetX)
        {
            bool add = true;
            int x, y, step = 0;
            for (y = 0; y < MapHeight; y++)
                for (x = 0; x < MapWidht; x++)
                {
                    if (field[y, x] == 0)
                        cMap[y, x] = -2;//индикатор стены
                    else
                        cMap[y, x] = -1;//индикатор еще не ступали сюда
                }
            cMap[targetY, targetX] = 0;//Начинаем с финиша
            while (add == true)
            {
                add = false;
                for (y = 0; y < MapWidht; y++)
                    for (x = 0; x < MapHeight; x++)
                    {
                        int[] dx = { -1, 1, 0, 0 };
                        int[] dy = { 0, 0, 1, -1 };
                        if (cMap[x, y] == step)
                        {
                            //Ставим значение шага+1 в соседние ячейки (если они проходимы)
                            if (y - 1 >= 0 && cMap[x - 1, y] != -2 && cMap[x - 1, y] == -1)
                                cMap[x - 1, y] = step + 1;
                            if (x - 1 >= 0 && cMap[x, y - 1] != -2 && cMap[x, y - 1] == -1)
                                cMap[x, y - 1] = step + 1;
                            if (y + 1 < MapWidht && cMap[x + 1, y] != -2 && cMap[x + 1, y] == -1)
                                cMap[x + 1, y] = step + 1;
                            if (x + 1 < MapHeight && cMap[x, y + 1] != -2 && cMap[x, y + 1] == -1)
                                cMap[x, y + 1] = step + 1;
                        }
                    }
                step++;
                add = true;
                if (cMap[startY, startX] != -1)
                {               //решение найдено
                    add = false;
                    cMap[startY, startX] = cMap.Length;
                }
                if (step > MapWidht * MapHeight)//решение не найдено
                    add = false;
            }
            //for (x = 0; x < MapWidht; x++)
            //{
            //    System.Diagnostics.Debug.Write("\n");
            //    for (y = 0; y < MapHeight; y++)
            //    {
            //        System.Diagnostics.Debug.Write(cMap[y, x]);
            //        System.Diagnostics.Debug.Write(" ");
            //    }
            //}


            //for (x = 0; x < MapWidht; x++)
            //{
            //    System.Diagnostics.Debug.Write("\n");
            //    for (y = 0; y < MapHeight; y++)

            //        if (cMap[y, x] == -1)
            //            System.Diagnostics.Debug.Write(" ");
            //        else
            //            if (cMap[y, x] == -2)
            //                System.Diagnostics.Debug.Write(" +");
            //            else
            //                if (y == startY && x == startX)
            //                    System.Diagnostics.Debug.Write("S");
            //                else
            //                    if (y == targetY && x == targetX)
            //                        System.Diagnostics.Debug.Write("F");
            //                    else
            //                        if (cMap[y, x] > -1)
            //                            System.Diagnostics.Debug.Write(" " + cMap[y, x]);

            //}
        }


        public void NewOrientation()
        {
            switch (rnd.Next(5)+1)
            {
                case 1: Or = _Orientation.Up; break;
                case 2: Or = _Orientation.Down; break;
                case 3: Or = _Orientation.Left; break;
                case 4: Or = _Orientation.Down; break;
                case 5: Or = _Orientation.Right; break;
            }
        }

        Image Image()
        {
            Image temp = tank.Properties.Resources.enemyImage;

            switch (Or)
            {
                case _Orientation.Up: break;
                case _Orientation.Down: temp.RotateFlip(RotateFlipType.Rotate180FlipNone); break;
                case _Orientation.Left: temp.RotateFlip(RotateFlipType.Rotate270FlipNone); break;
                case _Orientation.Right: temp.RotateFlip(RotateFlipType.Rotate90FlipNone); break;
            }

            return temp;
        }

        public void StartShoot()
        {
            Bullet = new _Bullet(maxWidth, maxHeight, Or);
            switch (Or)
            {
                case _Orientation.Down:
                case _Orientation.Up:
                    Bullet.StartShoot(Location, new Size(Size.Width, Size.Height + 16), Or, true); break;
                case _Orientation.Left:
                case _Orientation.Right:
                    Bullet.StartShoot(Location, new Size(Size.Width + 16, Size.Height), Or, true); break;

            }
        }
        
        public void Draw(Graphics graphics)
        {
            graphics.DrawImage(Image(), Location);
            if (Bullet.IsRunning)
                Bullet.Draw(graphics);
        }


        bool RectIntersect(Rectangle rect1, Rectangle rect2)
        {
            bool intersect = false;

            if (rect1.Left >= rect2.Left && rect1.Left <= rect2.Right && rect1.Top >= rect2.Top && rect1.Top <= rect2.Bottom
               || rect1.Left >= rect2.Left && rect1.Left <= rect2.Right && rect1.Bottom >= rect2.Top && rect1.Bottom <= rect2.Bottom
               || rect1.Right >= rect2.Left && rect1.Right <= rect2.Right && rect1.Top >= rect2.Top && rect1.Top <= rect2.Bottom
               || rect1.Right >= rect2.Left && rect1.Right <= rect2.Right && rect1.Bottom >= rect2.Top && rect1.Bottom <= rect2.Bottom)
                intersect = true;

            return intersect;
        }
    }
}
